package com.sugon.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AuthCheck;
import com.sugon.annotation.LoginUser;
import com.sugon.dao.SparePartConsumRecordDao;
import com.sugon.entity.*;
import com.sugon.entity.dto.SpConsumeParam;
import com.sugon.modules.sparepart.consts.SparePartsConsumeType;
import com.sugon.modules.sys.consts.SysDeptConst;
import com.sugon.service.*;
import com.sugon.utils.PageUtils;
import com.sugon.utils.Query;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 备件耗用记录Controller
 *
 * @author YuXD
 * @date 2023-09-12 09:11:28
 */
@Api(tags = "备件领用接口API")
@RestController
@Controller
@RequestMapping("/api/v1/spConsume")
public class SparePartConsumApiController {

    @Resource
    private SparePartConsumRecordService sparePartConsumRecordService;
    @Resource
    private SpareStorePosService spareStorePosService;
    @Resource
    private DevRepairRecordService repairRecordService;
    @Resource
    private DevMaintenanceTicketService devPmTicketService;
    @Resource
    private DevAmTicketService devAmTicketService;
    @Resource
    private EnergyDevRepairRecordService energyDevRepairRecordService;
    @Resource
    private MaterialRecordService materialRecordService;
    @Resource
    private SparePartConsumRecordDao sparePartConsumRecordDao;

    @AuthCheck
    @ApiOperation(value = "查看工单换件列表API")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "类型。REPAIR(维修耗用) MAINTENANCE(预防维护)", allowableValues = "REPAIR,MAINTENANCE", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "businessId", value = "工单ID", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", required = true),
            @ApiImplicitParam(name = "limit", value = "每页记录数", paramType = "query", dataType = "int", required = true)
    })
    @PostMapping
    public ApiResult<PageUtils> list(@RequestParam Map<String, Object> params) {
        ApiResult<PageUtils> apiResult = new ApiResult<>();
        //查询列表数据
        Query query = new Query(params);
        List<SparePartConsumRecordEntity> sparePartConsumRecordList = sparePartConsumRecordService.queryList(query);
        int total = sparePartConsumRecordService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(sparePartConsumRecordList, total, query.getLimit(), query.getPage());
        return apiResult.success(pageUtil);
    }

    @AuthCheck
    @ApiOperation(value = "查看可更换/选择的备件列表API")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "materialType", value = "领料单类型：2:维修领料,3:预防维护领料", allowableValues = "2,3", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", required = true),
            @ApiImplicitParam(name = "limit", value = "每页记录数", paramType = "query", dataType = "int", required = true)
    })
    @PostMapping("/listReplacable")
    public ApiResult<PageUtils> list(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam Map<String, Object> params) {
        ApiResult<PageUtils> apiResult = new ApiResult<>();
        // 默认只看当前车间的领料记录
        String workshopId = loginUser.getWorkShopId();
        if (StrUtil.isNotEmpty(workshopId) && !StrUtil.equals(SysDeptConst.ZZC_CODE, workshopId)) {
            params.put("deptId", workshopId);
        }
        params.put("isReplaceable", 1);
        //查询列表数据
        Query query = new Query(params);
        List<MaterialRecordEntity> materialRecordList = materialRecordService.queryList(query);
        int total = materialRecordService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(materialRecordList, total, query.getLimit(), query.getPage());
        return apiResult.success(pageUtil);
    }

    protected ApiResult getValidApiResult(BindingResult validResult) {
        // 基础校验是否通过
        if (validResult.hasErrors()) {
            StringBuilder sb = new StringBuilder();
            List<FieldError> fieldErrors = validResult.getFieldErrors();
            if (CollectionUtil.isNotEmpty(fieldErrors)) {
                for (FieldError fieldError : fieldErrors) {
                    sb.append(",").append(fieldError.getDefaultMessage());
                }
            }
            if (StrUtil.isNotEmpty(sb.toString())) {
                return new ApiResult().failMsg(sb.toString().replaceFirst(",", ""));
            }
        }
        return null;
    }

    @AuthCheck
    @ApiOperation(value = "添加换件记录API", notes = "目前移动端只支持维修换件、预防维护换件、自主维护换件")
    @PostMapping("/addConsumeRecord")
    @ResponseBody
    public ApiResult<String> save(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestBody @Validated SpConsumeParam spConsumeParam, BindingResult bindingResult) {
        // 常规校验
        ApiResult<String> apiResult = getValidApiResult(bindingResult);
        if (apiResult != null) {
            return apiResult;
        }
        apiResult = new ApiResult<>();
        // 新建备件领用记录
        SparePartConsumRecordEntity sparePartConsumRecord = new SparePartConsumRecordEntity();
        BeanUtil.copyProperties(spConsumeParam, sparePartConsumRecord);
        // 备件耗用类别必填
        String type = spConsumeParam.getType();
        if (StrUtil.isEmpty(type)) {
            return apiResult.failMsg("备件耗用类别必填！");
        }
        // 校验耗用类别是否合法
        if (!StrUtil.equalsAny(type, SparePartsConsumeType.getEnumValues())) {
            return apiResult.failMsg("非法耗用类别！");
        }
        /*
            设备维修、维护、自主维护时换件，需要从各车间的领料列表中进行选择
            COMMON耗用时，是从库位选择的，需要走正常出库流程
         */
        if (StrUtil.equals(type, SparePartsConsumeType.COMMON.name())) {
            return apiResult.failMsg("目前不支持常规维修换件，请通过电脑端进行操作！");
        } else {
            // 工单信息必填
            if (!StrUtil.isAllNotEmpty(spConsumeParam.getType(), spConsumeParam.getBusinessId())) {
                return apiResult.failMsg("工单信息必填！");
            }
            if (SparePartsConsumeType.REPAIR.name().equals(spConsumeParam.getType())) {
                // 校验设备维修记录是否存在
                DevRepairRecordEntity repairRecord = repairRecordService.queryObject(spConsumeParam.getBusinessId());
                if (repairRecord == null) {
                    return apiResult.failMsg("设备维修工单不存在，请确认！");
                }
                // 设备维修时领料单明细必填
                if (StrUtil.isEmpty(spConsumeParam.getMaterialRecordId())) {
                    return apiResult.failMsg("设备维修时，领料明细必填！");
                }
                // 校验领料明细是否存在
                MaterialRecordEntity materialItem = materialRecordService.queryObject(spConsumeParam.getMaterialRecordId());
                if (materialItem == null) {
                    return apiResult.failMsg("领料明细不存在，请确认！");
                }
                sparePartConsumRecord.setDevId(repairRecord.getDevId());
                sparePartConsumRecord.setSparePartId(materialItem.getSpareId());
                sparePartConsumRecord.setTicketCode(repairRecord.getRepairCode());
            }
            if (SparePartsConsumeType.ENERGY_REPAIR.name().equals(sparePartConsumRecord.getType())) {
                EnergyDevRepairRecord repairRecord = energyDevRepairRecordService.queryObject(sparePartConsumRecord.getBusinessId());
                if (repairRecord == null) {
                    return apiResult.failMsg("设备维修工单不存在，请确认！");
                }
                sparePartConsumRecord.setDevId(repairRecord.getDevId());
                sparePartConsumRecord.setTicketCode(repairRecord.getId());
            } else if (SparePartsConsumeType.MAINTENANCE.name().equals(sparePartConsumRecord.getType())) {
                DevMaintenanceTicketEntity maintenanceTicket = devPmTicketService.queryObject(sparePartConsumRecord.getBusinessId());
                if (maintenanceTicket == null) {
                    return apiResult.failMsg("设备维护工单不存在，请确认！");
                }
                // 校验领料明细是否存在
                MaterialRecordEntity materialItem = materialRecordService.queryObject(sparePartConsumRecord.getMaterialRecordId());
                if (materialItem == null) {
                    return apiResult.failMsg("领料明细不存在，请确认！");
                }
                sparePartConsumRecord.setDevId(maintenanceTicket.getDevId());
                sparePartConsumRecord.setSparePartId(materialItem.getSpareId());
                sparePartConsumRecord.setTicketCode(maintenanceTicket.getRepairCode());
            } else if (SparePartsConsumeType.AM.name().equals(sparePartConsumRecord.getType())) {
                DevAmTicketEntity devAmTicket = devAmTicketService.queryObject(sparePartConsumRecord.getBusinessId());
                if (devAmTicket == null) {
                    return apiResult.failMsg("设备自主维护工单不存在，请确认！");
                }
                sparePartConsumRecord.setDevId(devAmTicket.getDevId());
                sparePartConsumRecord.setTicketCode(devAmTicket.getRepairCode());
            }
        }
        sparePartConsumRecord.setCreateUser(loginUser.getUserId());
        // 保存耗用记录
        boolean saveFlag = sparePartConsumRecordService.save(sparePartConsumRecord) > 0;
        Assert.isTrue(saveFlag);
        // 调整领料数
        sparePartConsumRecordService.modifyConsumeNum(sparePartConsumRecord);
        return apiResult.success();
    }

    @AuthCheck
    @ApiOperation(value = "调整领用数API")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "换件记录ID", paramType = "query", dataType = "string", required = true),
            @ApiImplicitParam(name = "num", value = "换件数量", paramType = "query", dataType = "int", required = true)
    })
    @PostMapping("/adjustConsumeNum")
    public ApiResult<String> adjustConsumeNum(@ApiIgnore @LoginUser SysUserEntity loginUser, @RequestParam String id, @RequestParam Integer num) {
        ApiResult<String> apiResult = new ApiResult<>();
        // 领用数不得小于0
        if (num <= 0) {
            return apiResult.failMsg("使用数量必须大于0！");
        }
        SparePartConsumRecordEntity consumeRecord = sparePartConsumRecordService.queryObject(id);
        if (consumeRecord == null) {
            return apiResult.failMsg("备件耗用记录不存在！");
        }
        /*
            如果是设备维修
         */
        if (StrUtil.equalsAny(consumeRecord.getType(), SparePartsConsumeType.REPAIR.name(), SparePartsConsumeType.MAINTENANCE.name())) {
            Assert.notEmpty(consumeRecord.getMaterialRecordId());
            MaterialRecordEntity materialItem = materialRecordService.queryObject(consumeRecord.getMaterialRecordId());
            Assert.notNull(materialItem);
            // 本次的领用数不得大于可用数
            int sumConsumeNum = sparePartConsumRecordDao.sumConsumeNum(id, consumeRecord.getMaterialRecordId());
            if (num > materialItem.getActualNum() - sumConsumeNum) {
                return apiResult.failMsg("当前领料明细中最大可以更换数为" + (materialItem.getActualNum() - sumConsumeNum) + " ，请确保使用数量不得大于该数！");
            }
        } else if (SparePartsConsumeType.ENERGY_REPAIR.name().equals(consumeRecord.getType())) {
            if (StrUtil.isNotEmpty(consumeRecord.getPosId())) {
                SpareStorePosEntity position = spareStorePosService.queryObject(consumeRecord.getPosId());
                Assert.notNull(position);
                if (num > position.getAvailableNum()) {
                    return apiResult.failMsg("当前备件库位可用库存数不足，请确认！");
                }
            }
        }
        consumeRecord.setNum(num);
        consumeRecord.setCreateUser(loginUser.getUserId());
        return sparePartConsumRecordService.modifyConsumeNum(consumeRecord) ? apiResult.success() : apiResult.failMsg("修改失败，请稍后重试！");
    }

    @AuthCheck
    @ApiOperation(value = "删除换件记录API")
    @PostMapping(value = "/delete")
    public ApiResult<String> delete(@RequestBody String[] ids) {
        ApiResult<String> apiResult = new ApiResult<>();
        return sparePartConsumRecordService.deleteBatch(ids) > 0 ? apiResult.success() : apiResult.failMsg("删除失败，请稍后重试！");
    }

}
